package bitmap;

import java.io.FileInputStream;
import java.io.FileOutputStream;

import colour.Colour;

/**
 * This is a class which realizes the operation of writing and reading groups of
 * colour component in binary which is identified by P6
 * 
 * @author Yuting Wu
 * @author Kan Lin
 * @author Bing Dong
 * 
 * @param width
 *            the width of the image
 * @param height
 *            the height of the image
 * @param maxColourValue
 *            maximal value can be handled
 * @param RGB
 *            vector for the RGB value
 * @param colour
 *            a single data type of colour component
 * @param colourNum
 *            storage the number of the colour component, which is used for
 *            testing
 */

public class BitmapInP6 implements IPPM {

	// the number shows the type of format
	// P3 is ASCII and P6 is binary
	private int width; // the width of the picture
	private int height; // the height of the picture
	private int maxColourValue;
	private Bitmap bpWrite;


	// Constructors
	public BitmapInP6(final int width, final int height,int maxColourValue) {

		this.width = width;
		this.height = height;
		this.maxColourValue = maxColourValue;

	}

	// Constructors
	public BitmapInP6(Bitmap bpWrite) {

		this.bpWrite = bpWrite;
		this.maxColourValue = bpWrite.getMaxColourValue();
		this.height = this.bpWrite.getHeight();
		this.width = this.bpWrite.getWidth();
		

	}

	

	/**
	 * Read each colour component in binary format without the influence by the
	 * whitespace into a Vector. It implements the interface IPPM.
	 * 
	 * @param fis
	 *            a FileInputStream for reading file
	 * @param firstByte
	 *            first value can be used
	 * @return a array stores all of the colour component
	 */
	public Colour[][] readColour(FileInputStream fis,
			final int firstByte) {

		Colour[][] pixels = new Colour[height][width];
		try {

			int value;// value gee from file
			int red = -1;
			int green = -1;
			int blue = -1;

			int number = 0;
			int nHeight = 0; // the position of height stored in array
			int nWidth = 0; // the position of width stored in array

			while (true) {
				value = fis.read();
				if (value == -1) {
					break;
				} else {
					red = value;

				}
				value = fis.read();
				if (value == -1) {
					break;
				} else {

					green = value;
				}
				value = fis.read();
				if (value == -1) {
					break;
				} else {
					blue = value;

				}

				// To check whether the dara of color component is right or
				// wrong
				if (valueCheck(red, green, blue)) {
					pixels[nHeight][nWidth] = new Colour(red, green, blue);
					number++;
				} else {
					System.out.println("The data of color component is wrong!");
					return null;
				}

				nWidth++;

				if (nWidth == this.width) {
					nHeight++;
					nWidth = 0;

				}
				if (number > this.height * this.width) {
					System.out
							.println("The number of color component is wrong!");
					return null;
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("some errors in reading colour in P6!");
			return null;
		}
		return pixels;
	}

	/**
	 * This is a method for checking whether the value is correct
	 * 
	 * @param red
	 * @param green
	 * @param blue
	 * @return
	 */
	private boolean valueCheck(int red, int green, int blue) {
		
		return (red <= maxColourValue && red >= 0
				&& green <= maxColourValue && green >= 0
				&& blue <= maxColourValue && blue >= 0);

	}

	//

	/**
	 * This method realizes the writing operation of colour component on image
	 * stored in PPM which is in binary format. It implements the interface
	 * IPPM.
	 * 
	 * @param fos
	 *            the stream for writing the colour component information the
	 *            stream has to be created to append
	 * @param whitespace
	 *            to divide between the colour component. In P6,it is useless.
	 * 
	 * @return a type of boolean shows whether the operation is sucessful
	 */

	public boolean writeColour(FileOutputStream fos, String whitespace) {

		boolean flag = true;
		if (bpWrite.checkNumEuqal()) {
			Colour colourValue;
			try {
				// for the right direction
				for (int i = 0; i < this.height; i++) {
					for (int j = 0; j < this.width; j++) {

						colourValue = bpWrite.getColourIndex(i,j);
						int[] rgb = colourValue.getRGB();
						fos.write(rgb[0]);
						fos.write(rgb[1]);
						fos.write(rgb[2]);

					}
				}
			} catch (Exception e) {
				System.out.println("some errors in wrtiting the colour "
						+ "component in binary format!");
				flag = false;
			}
		} else {
			System.out.println("The number of color component is wrong!");
			flag = false;
		}
		return flag;
	}

}
